/*
Copyright (C) 1996-1997 GX Media, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "stdafx.h"
#ifdef _WIN32
#include <direct.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#endif
#include "Game.h"
#include "QDraw.h"

Game *Game::game = NULL;
LinkList<Game> Game::games;

Game::Game(int numUtils) {
	games.AppendNode(*this);
	initialized = false;
	exportWad = false;
	specifyWads = false;
	qualifiedTextures = false;
	
	cfg = NULL;

	gameName = wxT("");
	gameDir = wxT("");
	mapDir = wxT("");
	texDir = wxT("");
	palName = wxT("");
	mapExt = wxT("map");

	texDB = NULL;
}

Game::~Game(void) {
	if(texDB)
		delete texDB;
}

void
Game::Exit(void) {
	while(games.NumOfElm() > 0)
		delete &(games.RemoveNode(0));
}

bool
Game::Set(Game *_game, const wxString &palName, float gamma) {
	ASSERT(_game != NULL);
	if (!_game->Init())
		return false;

	game = _game;
	
	if(!palName.empty())
		game->palName = palName;
	else		
		game->palName = game->GetPalDef();

	game->pal.Load(game->palName, gamma);

	return true;
}

Game *
Game::Get(void) {
	return game;
}

Game *
Game::Find(const wxString &name) {
	IterLinkList<Game> iter(games);

	iter.Reset();
	while(!iter.IsDone()) {
		Game *pGame = iter.GetNext();
		if(pGame->gameName == name)
			return pGame;
	}

	return NULL;
}

// Game map parameters.
int Game::GetDefaultGridSize() const
{
	return 16;
}

int Game::GetDefaultRotSnapSize() const
{
	return 15;
}

int Game::GetGridSteps() const
{
	return 4;
}

int Game::GetGridSizeBase() const
{
	return 2;
}

float Game::GetNearPlane() const
{
	return 1.0f;
}

float Game::GetFarPlane() const
{
	return 1000.0f;
}

// Primitives set
const wxString &Game::GetPrimitivesSet() const
{
	static wxString ret = wxT("brushes/imperial.xml");
	return ret;
}

//===== Additional properties pages. =====
unsigned int Game::GetExtraPropPages(void) const {
	// Default to add nothing.
	return 0;
}

//===== Additional game sets. ====
int Game::GetNumGameSets()
{
	return 0;
}

void Game::GetGameSet(int index, wxString &name, wxString &entName, wxString &palName)
{
}

//===== Compile map stuff. =====
const wxString &Game::GetUtilPath(int index) const
{
	return utilsPath[index];
}

void Game::SetUtilPath(int index, const wxString &path)
{
	utilsPath[index] = path;
}

void Game::InitCompileParams(bool runUtils[], wxString params[],
							 int &paramIndex) const {
	int i, numUtils = GetNumUtils();

	for(i = 0; i < numUtils; i++) {
		runUtils[i] = ((runUtilsFlag & (0x01 << i)) != 0);
		params[i] = wxString(utilsParams[i], wxConvUTF8);
	}

	paramIndex = setPIndex;
}

void Game::SaveCompileParams(bool runUtils[], wxString params[],
							 int &paramIndex) {
	int i, numUtils = GetNumUtils();
	runUtilsFlag = 0x00;

	for(i = 0; i < numUtils; i++) {
		runUtilsFlag |= (runUtils[i] ? (0x01 << i) : 0);
		utilsParams[i] = params[i];
	}

	setPIndex = paramIndex;
}

const wxString &Game::GetMapExportPath(const wxString &docName,
								   OutTextProc pTextProc) const {
	static wxString empty;
	static wxString mapPath;
	ASSERT(!docName.empty());

	// Make sure the dir exists.
	if (!LFile::ExistDir(mapDir)) {
		// Need to create the dir.
		if (pTextProc != NULL) {
			wxString textBuf;
			textBuf.Printf(_("Creating directory: %s\n"), mapDir.c_str());
			(*pTextProc)(textBuf.c_str());
		}

#ifdef _WIN32
		if (_mkdir(mapDir.utf8_str()) != 0) {
#else
		if (mkdir(mapDir.utf8_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
#endif
			if (pTextProc != NULL)
				(*pTextProc)(_("Failed to create directory.\n"));
			return empty;
		}
	}

	// Clean up the map Dir.
	CleanUpCompile(docName, false, pTextProc);

	// Derive the export map file path.
	mapPath = mapDir + wxT("/") + docName + wxT(".") + mapExt;

	return mapPath;
}

bool Game::GetUtilCmdLine(int utilIndex, const wxString &docName,
						   wxString *cmdLine, wxString *initDir,
						   OutTextProc pTextProc) const {
	ASSERT(!docName.empty());
	ASSERT(cmdLine);
	ASSERT(initDir);

	int numUtils = GetNumUtils();

	if (utilIndex < 0 || utilIndex >= numUtils)
		return false;

	cmdLine->Printf(wxT("%s %s"), utilsPath[utilIndex].c_str(),
			utilsParams[utilIndex].c_str());
	cmdLine->Replace(wxT("%file%"), docName.c_str());
	cmdLine->Replace(wxT("%FILE%"), docName.c_str());

#ifndef _WIN32
	// Run through wine windows programs.
	if(wxFileName(utilsPath[utilIndex]).GetExt().CmpNoCase(wxT("exe")) == 0)
		*cmdLine = wxT("wine ") + *cmdLine;
#endif

	// InitDir
	if (utilIndex != numUtils - 1)
		*initDir = mapDir;
	else
		*initDir = gameDir;

	return true;
}

void Game::CleanUpCompile(const wxString &docName, bool skipBSP, OutTextProc pTextProc) const {
	ASSERT(!docName.empty());

	if (!LFile::ExistDir(mapDir))
		return;

	// Clean up the map dir.
	wxString textBuf;
	wxString files = docName + wxT(".*");
	LFindFiles delFiles(mapDir, files);

	bool skipLine = false;
	wxString delFName;
	wxString fext;
	while (!(delFName = delFiles.Next()).empty()) {
		fext = delFName.substr(delFName.rfind(wxT(".")));
		if (fext == wxT(".bsp") && skipBSP)
			continue;  // Skip the .bsp file.
		if (fext == wxT(".map") && skipBSP)
			continue;  // Skip the .map file.
		if (fext == wxT(".qle"))
			continue;  // Skip the .qle

		if (pTextProc != NULL)
		{
			textBuf.Printf(_("Deleting file: %s\n"), delFName.c_str());
			(*pTextProc)(textBuf.c_str());
		}
		textBuf.Printf(wxT("%s/%s"), mapDir.c_str(), delFName.c_str());
#ifdef _WIN32
		_unlink(textBuf.utf8_str());
#else
		unlink(textBuf.utf8_str());
#endif
		skipLine = true;
	}

	if (skipLine && pTextProc != NULL)
		(*pTextProc)(wxT("\n"));
}

Texture *Game::GetDefaultTexture(void) {
	return texDB->FindTexture(defTexture);
}

void Game::ExtractTextures(void) {
}

bool Game::LoadTextureSizes(Texture *texture, const wxString &filename, int offset)
{
	return LoadTexture(texture, filename, offset);
}

void ExtractTexsFromPak(LPak *pak, const wxString &baseDir) {
	char outname[MAX_PATH];
	char dirname[MAX_PATH];
	char *name, *c;
	int i, count = 0, total = 0;

	for(i = 0; i < pak->entries; i++)
		if(strstr(pak->entry[i].filename, ".wal"))
			total++;

	ASSERT(NULL);
	/*CProgressWnd progressWnd(AfxGetMainWnd(), "Progress");
	progressWnd.SetText("Extracting Textures");
	QDraw::OutputText("Extracting textures from Pak... ");

	SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT)));*/

	for(i = 0; i < pak->entries; i++) {
		name = pak->entry[i].filename;
		if(strstr(name, ".wal")) {
			sprintf(outname, "%s/%s", (const char*)baseDir.utf8_str(), name);
			strcpy(dirname, outname);
			c = strrchr(dirname, '/');
			if(!c)
				c = strrchr(dirname, '\\');
			if(c)
				*c = 0;

			LFile::MakeDir(wxString(dirname, wxConvUTF8));
			LFile::Extract(wxString(name, wxConvUTF8), wxString(outname, wxConvUTF8));

			/*progressWnd.SetPos(count++ * 100 / total);
			progressWnd.PeekAndPump();

			if(progressWnd.Cancelled())
			{
				QDraw::OutputText("Cancelled.\n");
				break;
			}*/
		}
	}

	//QDraw::OutputText("OK.\n");
	//progressWnd.Clear();
	//SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
}

